home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / jnos110g.zip / SOCKUSER.C < prev    next >
C/C++ Source or Header  |  1994-05-27  |  18KB  |  764 lines

  1. /* Higher level user subroutines built on top of the socket primitives
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by PA0GRI
  5.  */
  6. #include "global.h"
  7. #ifdef  ANSIPROTO
  8. #include <stdarg.h>
  9. #endif
  10. #include "mbuf.h"
  11. #include "proc.h"
  12. #include "socket.h"
  13. #ifdef  LZW
  14. #include "lzw.h"
  15. #endif
  16. #include "usock.h"
  17. #include "session.h"
  18. #include "nr4.h"
  19.   
  20. /*
  21. #define oldusputs
  22. */
  23.   
  24. #ifdef LINUX
  25. /*
  26.  * Set this to 1 to force the next tcmdprintf() to the Command session regard-
  27.  * less of the existence of a trace session.  Not the best interface...
  28.  */
  29. int CmdOverride = 0;
  30. #endif
  31.   
  32. /* Higher-level receive routine, intended for connection-oriented sockets.
  33.  * Can be used with datagram sockets, although the sender id is lost.
  34.  */
  35. int
  36. recv(s,buf,len,flags)
  37. int s;      /* Socket index */
  38. char *buf;  /* User buffer */
  39. int len;    /* Max length to receive */
  40. int flags;  /* Unused; will eventually select oob data, etc */
  41. {
  42.     struct mbuf *bp;
  43.     int cnt;
  44.   
  45.     if(len == 0)
  46.         return 0;   /* Otherwise would be interp as "all" */
  47.   
  48.     cnt = recv_mbuf(s,&bp,flags,NULLCHAR,(int *)NULL);
  49.     if(cnt > 0){
  50.         cnt = min(cnt,len);
  51.         pullup(&bp,buf,(int16)cnt);
  52.         free_p(bp);
  53.     }
  54.     return cnt;
  55. }
  56. /* Higher level receive routine, intended for datagram sockets. Can also
  57.  * be used for connection-oriented sockets, although from and fromlen are
  58.  * ignored.
  59.  */
  60. int
  61. recvfrom(s,buf,len,flags,from,fromlen)
  62. int s;      /* Socket index */
  63. char *buf;  /* User buffer */
  64. int len;    /* Maximum length */
  65. int flags;  /* Unused; will eventually select oob data, etc */
  66. char *from; /* Source address, only for datagrams */
  67. int *fromlen;   /* Length of source address */
  68. {
  69.     struct mbuf *bp;
  70.     register int cnt;
  71.   
  72.     cnt = recv_mbuf(s,&bp,flags,from,fromlen);
  73.     if(cnt > 0){
  74.         cnt = min(cnt,len);
  75.         pullup(&bp,buf,(int16)cnt);
  76.         free_p(bp);
  77.     }
  78.     return cnt;
  79. }
  80. /* High level send routine */
  81. int
  82. send(s,buf,len,flags)
  83. int s;      /* Socket index */
  84. char *buf;  /* User buffer */
  85. int len;    /* Length of buffer */
  86. int flags;  /* Unused; will eventually select oob data, etc */
  87. {
  88.     register struct mbuf *bp;
  89.     char sock[MAXSOCKSIZE];
  90.     int i = MAXSOCKSIZE;
  91.   
  92.     if(getpeername(s,sock,&i) == -1)
  93.         return -1;
  94.     bp = qdata(buf,(int16)len);
  95.     return send_mbuf(s,bp,flags,sock,i);
  96. }
  97. /* High level send routine, intended for datagram sockets. Can be used on
  98.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  99.  */
  100. int
  101. sendto(s,buf,len,flags,to,tolen)
  102. int s;      /* Socket index */
  103. char *buf;  /* User buffer */
  104. int len;    /* Length of buffer */
  105. int flags;  /* Unused; will eventually select oob data, etc */
  106. char *to;   /* Destination, only for datagrams */
  107. int tolen;  /* Length of destination */
  108. {
  109.     register struct mbuf *bp;
  110.   
  111.     bp = qdata(buf,(int16)len);
  112.     return send_mbuf(s,bp,flags,to,tolen);
  113. }
  114. /* Receive a newline-terminated line from a socket, returning # chars read.
  115.  * The end-of-line sequence is recognized and translated into a single '\n'.
  116.  */
  117. int
  118. recvline(s,buf,len)
  119. int s;      /* Socket index */
  120. char *buf;  /* User buffer */
  121. unsigned len;   /* Length of buffer */
  122. {
  123.     int c;
  124.     int cnt = 0;
  125.   
  126.     while(len-- > 1){
  127.         if((c = recvchar(s)) == EOF){
  128.             cnt = -1;
  129.             break;
  130.         }
  131.         if(buf != NULLCHAR)
  132.             *buf++ = c;
  133.         cnt++;
  134.         if(uchar(c) == '\n')
  135.             break;
  136.     }
  137.     if(buf != NULLCHAR)
  138.         *buf = '\0';
  139.     return cnt;
  140. }
  141. #if defined(ANSIPROTO)
  142. /* Do printf on a user socket */
  143. int
  144. usprintf(int s,char *fmt,...)
  145. {
  146.     va_list args;
  147.     int len;
  148.   
  149.     va_start(args,fmt);
  150.     len = usvprintf(s,fmt,args);
  151.     va_end(args);
  152.     return len;
  153. }
  154. /* Printf on standard output socket */
  155. int
  156. tprintf(char *fmt,...)
  157. {
  158.     va_list args;
  159.     int len;
  160.   
  161.     va_start(args,fmt);
  162.     len = usvprintf(Curproc->output,fmt,args);
  163.     va_end(args);
  164.     return len;
  165. }
  166.   
  167. #ifdef LINUX
  168.   
  169. /* Print on Command stdout socket (for trace) */
  170. int
  171. tcmdprintf(FILE *fp, char *fmt, ...)
  172. {
  173.     extern struct session *Trace;
  174.     extern int Tracesession;
  175.     extern int CmdOverride;
  176.     int tsock, oldflow;
  177.     va_list args;
  178.     int len;
  179.   
  180.     va_start(args,fmt);
  181.     if (fp == stdout)
  182.     {
  183.         if (Tracesession && !CmdOverride)
  184.             tsock = Trace->output;
  185.         else
  186.         {
  187.             tsock = Command->output;
  188.       /*
  189.        * If they're using tcmdprintf, they don't want flow control.
  190.        * Otherwise, they'll get "More?" every 24 lines and tracing
  191.        * will lock up... and with it, the entire system.
  192.        * domain.c uses a different routine, since it wants to choose
  193.        * between the Command session and a file but it wants paging,
  194.        * and definitely wants a More? prompt.
  195.        */
  196.             oldflow = Command->flowmode;
  197.             Command->flowmode = 0;
  198.             CmdOverride = 0; /* override only works once */
  199.         }
  200.         len = usvprintf(tsock, fmt, args);
  201.         if (tsock == Command->output)
  202.             Command->flowmode = oldflow;
  203.     }
  204.     else
  205.         len = vfprintf(fp, fmt, args);
  206.     va_end(args);
  207.     return len;
  208. }
  209.   
  210. /* Print on Command stdout socket (only) or a file */
  211. int
  212. tfprintf(FILE *fp, char *fmt,...)
  213. {
  214.     va_list args;
  215.     int len;
  216.   
  217.     va_start(args,fmt);
  218.     if (fp == stdout)
  219.         len = usvprintf(Command->output, fmt, args);
  220.     else
  221.         len = vfprintf(fp, fmt, args);
  222.     va_end(args);
  223.     return len;
  224. }
  225.   
  226. #endif
  227.   
  228. /* The guts of printf, uses variable arg version of sprintf */
  229. int
  230. usvprintf(int s,char *fmt, va_list args)
  231. {
  232.     int len,withargs;
  233.     char *buf;
  234.   
  235.     if(strchr(fmt,'%') == NULLCHAR){
  236.         /* Common case optimization: no args, so we don't
  237.          * need vsprintf()
  238.          */
  239.         withargs = 0;
  240.         buf = fmt;
  241.         len = strlen(fmt);
  242.     } else {
  243.         /* Use a default value that is hopefully longer than the
  244.          * biggest output string we'll ever print (!)
  245.          */
  246.         withargs = 1;
  247.         buf = mallocw(SOBUF);
  248. /* Start of mod by N4YYH */
  249.         if((len=vsprintf(buf,fmt,args)) >= SOBUF) {
  250.             /* It's too late to be sorry. He's dead, Jim. */
  251. #ifdef STKTRACE
  252.             stktrace();
  253. #endif
  254.             log(s,"usvprintf() has exceeded the size of it's buffer. Restarting NOS.");
  255.             where_outta_here(1);
  256.         }
  257. /* End of mod by N4YYH */
  258. /*
  259.         len = strlen(buf);
  260. */
  261.     }
  262.     if(usputs(s,buf) == EOF)
  263.         len = -1;
  264.     if(withargs)
  265.         free(buf);
  266.     return len;
  267. }
  268. #else
  269. /*VARARGS*/
  270. /* Printf to standard output socket */
  271. int
  272. tprintf(fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  273. char *fmt;      /* Message format */
  274. int arg1,arg2,arg3; /* Arguments */
  275. int arg4,arg5,arg6;
  276. int arg7,arg8,arg9;
  277. int arg10,arg11,arg12;
  278. {
  279.     return usprintf(Curproc->output,fmt,arg1,arg2,arg3,arg4,arg5,arg6,
  280.     arg7,arg8,arg9,arg10,arg11,arg12);
  281. }
  282. /* Printf to socket. Doesn't use ANSI vsprintf */
  283. int
  284. usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  285. int s;          /* Socket index */
  286. char *fmt;      /* Message format */
  287. int arg1,arg2,arg3; /* Arguments */
  288. int arg4,arg5,arg6;
  289. int arg7,arg8,arg9;
  290. int arg10,arg11,arg12;
  291. {
  292.     int len,withargs;
  293.     char *buf;
  294.   
  295.     if(strchr(fmt,'%') == NULLCHAR){
  296.         /* No args, so we don't need vsprintf() */
  297.         withargs = 0;
  298.         buf = fmt;
  299.         len = strlen(fmt);
  300.     } else {
  301.         /* Use a default value that is hopefully longer than the
  302.          * biggest output string we'll ever print (!)
  303.          */
  304.         withargs = 1;
  305.         buf = mallocw(SOBUF);
  306. /* Start of mod by N4YYH */
  307.         if((len=sprintf(buf,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,
  308.         arg8,arg9,arg10,arg11,arg12)) >= SOBUF) {
  309.             /* It's too late to be sorry. He's dead, Jim. */
  310.             log(s,"usvprintf() has exceeded the size of it's buffer. Restarting NOS.");
  311.             where_outta_here(1);
  312.         }
  313. /* End of mod by N4YYH */
  314. /*        len = strlen(buf);    */
  315.     }
  316.     if(usputs(s,buf) == EOF)
  317.         len = -1;
  318.   
  319.     if(withargs)
  320.         free(buf);
  321.     return len;
  322. }
  323. #endif
  324.   
  325. /* Buffered putchar to a socket */
  326. int
  327. usputc(s,c)
  328. int s;
  329. char c;
  330. {
  331.     struct usock *up;
  332.     register struct mbuf *bp;
  333.     char *cp;
  334.     int newline,len;
  335.   
  336.     if((up = itop(s)) == NULLUSOCK){
  337.         errno = EBADF;
  338.         return -1;
  339.     }
  340.     if(c == '\n' && (up->flag & SOCK_ASCII)){
  341.         newline = 1;
  342.         len = strlen(up->eol);
  343.     } else {
  344.         newline = 0;
  345.         len = 1;
  346.     }
  347. #ifndef LZW
  348.     /* Make sure there's room in the current buffer, if any */
  349.     if((bp = up->obuf) != NULLBUF){
  350.         if((bp->cnt >= bp->size - len) && usflush(s) == -1)
  351.             return EOF;
  352.     }
  353. #endif
  354.     if(up->obuf == NULLBUF){
  355.         /* Allocate a buffer of appropriate size */
  356. #ifdef notdef
  357.         /* since I now fragment nr4 packets in send_nr4(),
  358.          * don't worry, be happy :-) - WG7J
  359.          */
  360.         switch(up->type){
  361.             case TYPE_NETROML4:
  362.                 up->obuf = ambufw(NR4MAXINFO);
  363.                 break;
  364.             default:
  365.                 up->obuf = ambufw(BUFSIZ);
  366.                 break;
  367.         }
  368. #endif
  369.         up->obuf = ambufw(BUFSIZ);
  370.     }
  371.     /* Note: the buffer must be larger than the end-of-line sequence! */
  372.     bp = up->obuf;
  373.     cp = &bp->data[bp->cnt];
  374.     if(newline){
  375.         /* Translate into appropriate end-of-line sequence */
  376. #ifdef  LZW
  377.         for(cp = up->eol;*cp != '\0';cp++)
  378.             if(up->zout == NULLLZW)
  379.                 bp->data[bp->cnt++] = *cp;
  380.             else
  381.                 lzwencode(s,*cp);
  382. #else
  383.         strncpy(cp,up->eol,len);
  384. #endif
  385.     } else {
  386. #ifdef  LZW
  387.         if(up->zout == NULLLZW)
  388.             bp->data[bp->cnt++] = c;
  389.         else
  390.             lzwencode(s,c);
  391.     }
  392. #else
  393.     *cp = c;
  394. }
  395. bp->cnt += len;
  396. #endif
  397.     /* Flush if necessary and leave enough room for a comming eol */
  398. if((c == up->flush && up->flush != -1) || bp->cnt >= bp->size-9)
  399.     if(usflush(s) == -1)
  400.         return -1;
  401.   
  402. #ifdef LOOKSESSION
  403. if(up->look)    /* Some one is looking at us ! */
  404.     usputc(up->look->output,c);
  405. #endif
  406.   
  407. return (int)uchar(c);
  408. }
  409.   
  410. /* Put a character to standard output socket */
  411. int
  412. tputc(c)
  413. char c;
  414. {
  415.     return usputc(Curproc->output,c);
  416. }
  417.   
  418. #ifndef oldusputs
  419. /* Buffered puts to a socket */
  420. int
  421. usputs(s,buf)
  422. int s;
  423. char *buf;
  424. {
  425.     register struct usock *up;
  426.     register struct mbuf *bp;
  427.     char *cp,*wp;
  428.     int16 len,clen;
  429.     int doflush;
  430.     int eol_len;
  431.     int16 flushpt;
  432.     int ascii;
  433. #ifdef LOOKSESSION
  434.     char *oldbuf;
  435. #endif
  436.   
  437.     if((up = itop(s)) == NULLUSOCK){
  438.         errno = EBADF;
  439.         return EOF;
  440.     }
  441. #ifdef LOOKSESSION
  442.     oldbuf = buf;
  443. #endif
  444. #ifdef  LZW
  445.     if(up->zout != NULLLZW){
  446.         while(*buf != '\0')
  447.             if(usputc(s,*buf++) == EOF)
  448.                 return EOF;
  449. #ifdef LOOKSESSION
  450.         if(up->look)
  451.             usputs(up->look->output,oldbuf);
  452. #endif
  453.         return 0;
  454.     }
  455. #endif
  456.     ascii = up->flag & SOCK_ASCII;
  457.     if(ascii)
  458.         eol_len = strlen(up->eol);
  459.     doflush = (up->flush != -1) && (strchr(buf,up->flush) != NULLCHAR);
  460.     len = strlen(buf);
  461.   
  462.     while(len != 0){
  463.         if(up->obuf == NULLBUF){
  464.             /* Allocate a buffer of appropriate size */
  465. #ifdef notdef
  466.             /* since I now fragment nr4 packets in send_nr4(),
  467.              * don't worry, be happy :-) - WG7J
  468.              */
  469.             switch(up->type){
  470.                 case TYPE_NETROML4:
  471.                     clen = NR4MAXINFO;
  472.                     break;
  473.                 default:
  474.                     clen = BUFSIZ;
  475.                     break;
  476.             }
  477. #endif
  478.             clen = BUFSIZ;
  479.             up->obuf = ambufw(clen);
  480.         }
  481.         /* Note: the buffer must be larger than the end-of-line sequence! */
  482.         bp = up->obuf;
  483.         wp = &bp->data[bp->cnt];
  484.         if(ascii && (cp = strchr(buf,'\n')) != NULLCHAR){
  485.             /* Copy up to, but not including, newline */
  486.             clen = cp - buf;
  487.         } else {
  488.             /* Copy whole thing */
  489.             clen = len;
  490.         }
  491.         /* ...but no more than the room available */
  492.         clen = min(clen,bp->size - bp->cnt);
  493.         if(clen != 0){
  494.             memcpy(wp,buf,clen);
  495.             wp += clen;
  496.             bp->cnt += clen;
  497.             buf += clen;
  498.             len -= clen;
  499.         }
  500.         /* Set flush threshold to allow for eol, if enabled */
  501.         if(ascii)
  502.             flushpt = bp->size - eol_len;
  503.         else
  504.             flushpt = bp->size;
  505.   
  506.         if(ascii && *buf == '\n' && bp->cnt < flushpt){
  507.             /* Add appropriate end-of-line sequence */
  508.             strncpy(wp,up->eol,eol_len);
  509.             wp += eol_len;
  510.             bp->cnt += eol_len;
  511.             buf++;  /* Skip newline in buffer */
  512.             len--;
  513.         }
  514.         if(bp->cnt >= flushpt){
  515.             /* Buffer full, flush and get another */
  516.             if(usflush(s) == -1)
  517.                 return EOF;
  518.         }
  519.     }
  520.     if(doflush && usflush(s) == -1)
  521.         return EOF;
  522.   
  523. #ifdef LOOKSESSION
  524.     if(up->look)        /* someone is looking at us ! */
  525.         usputs(up->look->output,oldbuf);
  526. #endif
  527.   
  528.     return 0;
  529. }
  530.   
  531. #else
  532.   
  533. int
  534. usputs(s,x)
  535. int s;
  536. register char *x;
  537. {
  538.     while(*x != '\0') {
  539.         if(usputc(s,*x++) == EOF)
  540.             return EOF;
  541.     }
  542.     return 0;
  543. }
  544. #endif
  545.   
  546. /* Put a string to standard output socket */
  547. int
  548. tputs(s)
  549. char *s;
  550. {
  551.     return usputs(Curproc->output,s);
  552. }
  553.   
  554. /* Read a raw character from a socket with stream buffering. */
  555. int
  556. rrecvchar(s)
  557. int s;          /* Socket index */
  558. {
  559.     register struct usock *up;
  560. #ifdef  LZW
  561.     register int c;
  562. #endif
  563.   
  564.     if((up = itop(s)) == NULLUSOCK)
  565.         return EOF;
  566. #ifdef  LZW
  567.     if(up->zin != NULLLZW)
  568.         if((c = lzwdecode(up)) != -1)
  569.             return c;
  570. #endif
  571.     /* Replenish if necessary */
  572.     if(up->ibuf == NULLBUF && recv_mbuf(s,&up->ibuf,0,NULLCHAR,0) <= 0)
  573.         return EOF;
  574.   
  575. #ifdef  LZW
  576.     if(up->zin != NULLLZW)
  577.         if((c = lzwdecode(up)) != -1)
  578.             return c;
  579.         else
  580.             return rrecvchar(s);    /* needs replenish */
  581. #endif
  582.     return PULLCHAR(&up->ibuf); /* Returns -1 if eof */
  583. }
  584. /* This function recognizes the end-of-line sequence for the stream
  585.  * and translates it into a single '\n'.
  586.  */
  587. int
  588. recvchar(s)
  589. int s;          /* Socket index */
  590. {
  591.     int c;
  592.     register struct usock *up;
  593.   
  594.     if((up = itop(s)) == NULLUSOCK)
  595.         return EOF;
  596.   
  597.     c = rrecvchar(s);
  598.   
  599.     if(c != up->eol[0] || !(up->flag & SOCK_ASCII)) {
  600. #ifdef LOOKSESSION
  601.         if(up->look)
  602.             usputc(up->look->output,c);
  603. #endif
  604.         return c;
  605.     }
  606.   
  607.     /* This is the first char of a eol sequence. If the eol sequence is
  608.      * more than one char long, eat the next character in the input stream.
  609.      */
  610.     if(up->eol[1] != '\0'){
  611.         (void)rrecvchar(s);
  612.     }
  613.   
  614. #ifdef LOOKSESSION
  615.     if(up->look) {
  616.         usputc(up->look->output,'\n');
  617.         /* In the case 'looking' is done from bbs connection,
  618.          * flush it here...
  619.          */
  620.         usflush(up->look->output);
  621.     }
  622. #endif
  623.   
  624.     return '\n';
  625. }
  626. /* Flush output on a socket stream */
  627. int
  628. usflush(s)
  629. int s;
  630. {
  631.     register struct usock *up;
  632.     struct mbuf *bp;
  633.   
  634.     if((up = itop(s)) == NULLUSOCK)
  635.         return -1;
  636.   
  637.     if(up->obuf != NULLBUF){
  638. #ifdef  LZW
  639.         if(up->zout != NULLLZW)
  640.             lzwflush(up);
  641. #endif
  642.         bp = up->obuf;
  643.         up->obuf = NULLBUF;
  644.         return send_mbuf(s,bp,0,NULLCHAR,0);
  645.     }
  646.   
  647. #ifdef LOOKSESSION
  648.     if(up->look)    /* Some one is looking at us, flush them as well */
  649.         usflush(up->look->output);
  650. #endif
  651.   
  652.     return 0;
  653. }
  654. /* Flush output socket */
  655. void
  656. tflush()
  657. {
  658.     usflush(Current->output);
  659. }
  660.   
  661. /* Print prompt and read one character */
  662. int
  663. keywait(prompt,flush)
  664. char *prompt;   /* Optional prompt */
  665. int flush;  /* Flush queued input? */
  666. {
  667.     int c;
  668.     int i,len;
  669.   
  670.     if(flush && socklen(Curproc->input,0) != 0)
  671.         recv_mbuf(Curproc->input,NULLBUFP,0,NULLCHAR,0); /* flush */
  672.     if(prompt == NULLCHAR)
  673.         prompt = "Hit enter to continue";
  674.     tprintf(prompt);
  675.     tflush();
  676.     c = recvchar(Curproc->input);
  677.     /* Get rid of the prompt */
  678.     for(i=len=strlen(prompt);i != 0;i--)
  679.         tputc('\b');
  680.     for(i=len;i != 0;i--)
  681.         tputc(' ');
  682.     for(i=len;i != 0;i--)
  683.         tputc('\b');
  684.     tflush();
  685.     return (int)c;
  686. }
  687.   
  688. /* Set the end-of-line sequence on a socket */
  689. int
  690. seteol(s,seq)
  691. int s;
  692. char *seq;
  693. {
  694.     register struct usock *up;
  695.   
  696.     if((up = itop(s)) == NULLUSOCK)
  697.         return -1;
  698.   
  699.     if(seq != NULLCHAR)
  700.         strncpy(up->eol,seq,sizeof(up->eol));
  701.     else
  702.         *up->eol = '\0';
  703.     return 0;
  704. }
  705. /* Enable/disable eol translation, return previous state */
  706. int
  707. sockmode(s,mode)
  708. int s,mode;
  709. {
  710.     struct usock *up;
  711.     int prev;
  712.   
  713.     if((up = itop(s)) == NULLUSOCK)
  714.         return -1;
  715.     usflush(s);
  716.     prev = up->flag;
  717.     switch(mode){
  718.         case SOCK_BINARY:
  719.         case SOCK_ASCII:
  720.             up->flag = mode;
  721.             break;
  722.         default:
  723.             break;
  724.     }
  725.     return prev;
  726. }
  727. /* Specify the character to trigger automatic output buffer
  728.  * flushing, or -1 to disable it. Return the previous setting.
  729.  */
  730. int
  731. setflush(s,c)
  732. int s;
  733. int c;
  734. {
  735.     register struct usock *up;
  736.     int old;
  737.   
  738.     if((up = itop(s)) == NULLUSOCK)
  739.         return -1;
  740.   
  741.     old = up->flush;
  742.     up->flush = c;
  743.     return old;
  744. }
  745.   
  746. /* Set the block mode on a socket - WG7J.
  747.  * Primarily used on convers.c to prevent backlog of data and
  748.  * usprintf() calls blocking because of it...
  749.  * returns previous mode
  750.  */
  751. int sockblock(int s,int value) {
  752.   
  753.     register struct usock *up;
  754.     int oldval;
  755.   
  756.     if((up = itop(s)) == NULLUSOCK)
  757.         return -1;
  758.   
  759.     oldval = up->noblock;
  760.     up->noblock = value;
  761.     return oldval;
  762. }
  763.   
  764.